package com.xxh.video.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xxh.dataaccess.dao.recall.UserHistoryRecDao;
import com.xxh.dataaccess.dao.VideoDao;
import com.xxh.dataaccess.dao.recall.UserProfileRecallDao;
import com.xxh.dataaccess.dao.recall.VideoSimarRecDao;
import com.xxh.dataaccess.entity.*;
import com.xxh.dataaccess.page.MongoPageHelper;
import com.xxh.dataaccess.page.PageResult;
import com.xxh.dataaccess.service.UserService;
import com.xxh.video.dto.QueryParam;
import com.xxh.video.service.CategoryService;
import com.xxh.video.service.VideoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Service("VideoService")
public class VideoServiceImpl implements VideoService {

    @Autowired
    VideoDao VideoDao;

    @Autowired
    CategoryService categoryService;

    @Autowired
    MongoTemplate mongoTemplate;

    @Autowired
    MongoPageHelper mongoPageHelper;

    @Autowired
    UserService userService;

    @Autowired
    VideoSimarRecDao videoSimarRecDao;

    @Autowired
    UserHistoryRecDao userHistoryRecDao;

    @Autowired
    UserProfileRecallDao userProfileRecallDao;


    //实现根据类别的复杂查询方法
    @Override
    public PageResult<Video> SelectVideosByCategory(QueryParam queryParam) {

        //获取所有的类别
        List<Category> all = categoryService.list(null);

        //参数校验
        int curPage = (null == queryParam.getCurPage()) ? 0 : queryParam.getCurPage();
        int size = (null == queryParam.getPageSize()) ? 20 : queryParam.getPageSize();
        String SortName = (null == queryParam.getSortName()) ? "view" : queryParam.getSortName();

        //当前请求是哪一个大类
        QueryWrapper<Category> wrapper = new QueryWrapper<>();
        wrapper.eq("cid", queryParam.getMainCategory());
        Category father = categoryService.getOne(wrapper);

        //当前父类的所有子类
        List<String> subnams = getChildren(father, all).stream().map(item -> {
            return item.getName();
        }).collect(Collectors.toList());
        Query query = new Query();
        //如果子类别为空，查询该大类下的所有视频
        if (0 == queryParam.getSubCategoryName().length()) {
            query.addCriteria(Criteria.where("tname").in(subnams));
        } else {
            //子类不为空
            query.addCriteria(Criteria.where("tname").is(queryParam.getSubCategoryName()));
        }
        //view | pubdate
        query.with(Sort.by(Sort.Direction.DESC, SortName));


        PageResult<Video> pageQuery = mongoPageHelper.pageQuery(query, Video.class, size, curPage);
        return pageQuery;
    }


    //直接查询所有
    @Override
    public Page<Video> pagingVideos(Integer cur, Integer size) {
        Page<Video> page = VideoDao.findAll(PageRequest.of(cur, size));
        return page;
    }


    /**
     * @param categoryNames 必须是顶级父类名称
     * @return
     */
    @Override
    public List<Video> getTop20ByCategoryName(String categoryNames) {
        //获取该大区下所有子类别
        List<Category> subMenus = categoryService.getSubMenus(categoryNames);
        //取出所有属于该大区子类别对应的视频
        List<String> NameList = subMenus.stream().map(item -> {
            return item.getName();
        }).collect(Collectors.toList());

        //取出视频结果并排序
        Query query = new Query();
        query.with(Sort.by(Sort.Direction.DESC, "view"));
        query.with(PageRequest.of(0, 20));
        query.addCriteria(Criteria.where("tname").in(NameList));

        return mongoTemplate.find(query, Video.class);
    }


    @Override
    public void AddLikeNum(String bv) {

        Query query = new Query(Criteria.where("bv").is(bv));
        //查出原来的
        Video video = mongoTemplate.findOne(query, Video.class);
        //原来的like+1
        mongoTemplate.upsert(query, new Update().set("like", video.getLike() + 1), "video");

    }

    @Override
    public PageResult<Movie> PageMovieByCategory(String cname, Integer cur, Integer size) {
        Pattern pattern = Pattern.compile("^.*" + cname + ".*$");
        Query query = new Query(Criteria.where("types").regex(pattern));
        PageResult<Movie> page = mongoPageHelper.pageQuery(query, Movie.class, size, cur);
        return page;
    }

    @Override
    public Video getVideoByBv(String bv) {
        Query query = new Query(Criteria.where("bv").is(bv));
        //查出原来的
        Video video = mongoTemplate.findOne(query, Video.class);
        return video;
    }

    @Override
    public boolean SaveVideo(Video v) {
        Video video = VideoDao.save(v);
        if (video != null) {
            return true;
        }
        return false;
    }

    //根据视频ID获取上传者
    @Override
    public User getVideoUp(String bv) {

        Query query = new Query(Criteria.where("bv").is(bv));
        //查出原来的
        Video video = mongoTemplate.findOne(query, Video.class);
        String name = video.getName();
        User user = userService.findByUserName(name);
        return user;
    }

    @Override
    public int update(Video v) {
        Video video = VideoDao.save(v);
        if (v != null) {
            return 1;
        }
        return 0;
    }

    @Override
    public List<Video> getSimairVideo(String bv) {
        VideoSimarRec recs = videoSimarRecDao.getVideoSimarRecByBv(bv);
        List<String> list = recs.getRec_list();
        List<Video> videos = VideoDao.findByBvIn(list);
        return videos;
    }

    @Override
    public List<Video> getVideoByUid(Long uid) {

        UserHistoryRecall userHistoryRecall = userHistoryRecDao.getByUid(uid);
        if (userHistoryRecall != null) {

            //根据用户画像的推荐结果
            UserProfileRecall userProfileRecall = userProfileRecallDao.findUserProfileRecallByUid(uid);
            List<String> upbvs = userProfileRecall.getBvs();

            //根据浏览历史记录推荐的结果
            List<String> uhbvs = userHistoryRecall.getRecs();

            //合并推荐结果，生成召回集
            ArrayList<String> bvs = new ArrayList<>();
            bvs.addAll(upbvs);
            bvs.addAll(uhbvs);

            //将召回集的视频随机打乱，取出20条
            Collections.shuffle(bvs);
            List<Video> videos = VideoDao.findByBvIn(bvs.subList(0, 20));
            return videos;
        } else {
            //新用户直接根据用户画像生成召回集
            UserProfileRecall userProfileRecall = userProfileRecallDao.findUserProfileRecallByUid(uid);
            List<String> bvs = userProfileRecall.getBvs();
            //将召回集的视频随机打乱，取出20条
            Collections.shuffle(bvs);
            List<Video> videos = VideoDao.findByBvIn(bvs.subList(0, 20));
            return videos;
        }
    }

    /**
     * @param root 当前需要子求取节点的元素
     * @param all  所有的元素
     * @return 当前元素的所有子元素
     */
    private List<Category> getChildren(Category root, List<Category> all) {
        List<Category> list = all.stream().filter(item -> {
            return item.getParentId().equals(root.getCid());
        }).collect(Collectors.toList());
        return list;
    }


    /**
     * 获取播放数量高的视频
     *
     * @return
     */
    public List<Video> getTopViewVideos() {
        //取出视频结果并排序
        Query query = new Query();
        query.with(Sort.by(Sort.Direction.DESC, "view"));
        query.with(PageRequest.of(0, 8));
        return mongoTemplate.find(query, Video.class);
    }

}
